package prefuse.data.util;

import prefuse.data.CascadedTable;
import prefuse.data.Table;

/**
 * RowManager instance that additionally takes into account tables which
 * inherit from a parent table but can also have their own, dedicated
 * columns.
 * 
 * @author <a href="http://jheer.org">jeffrey heer</a>
 */
public class CascadedRowManager extends FilteredRowManager {
    
    /**
     * Create a new CascadedRowManager.
     * @param table the table to manage
     */
    public CascadedRowManager(Table table) {
        super(table);
    }
    
    /**
     * @see prefuse.data.util.RowManager#getColumnRow(int, int)
     */
    public int getColumnRow(int row, int col) {
        if ( !isValidRow(row) )
            return -1;
        else if ( col >= ((CascadedTable)getTable()).getLocalColumnCount() ){
        	Table parent = ((CascadedTable)m_table).getParentTable();
        	//WEENY(2010-09-18): we update the col to point at col in parent
        	//the original one does not update the col value, so when col is
        	//very big, you may result in finding the corresponding row in the
        	//root table, but the actual column may exist in the middle table.
        	//so the row index may be bigger than the middle table size, and you
        	//will get an exception! the following code shows this case:
        	//    		Table table = new Table();
        	//    		table.addColumn("A", boolean.class);
        	//    		table.getTuple(table.addRow()).setBoolean("A", true);
        	//    		table.getTuple(table.addRow()).setBoolean("A", false);
        	//    		table.getTuple(table.addRow()).setBoolean("A", true);
        	//    		table.getTuple(table.addRow()).setBoolean("A", false);
        	//    		table.getTuple(table.addRow()).setBoolean("A", true);
        	//    		CascadedTable child = 
        	//    			new CascadedTable(table, new ColumnExpression("A"));
        	//    		child.addColumn("B", boolean.class, false);
        	//    		child.setBoolean(0, "B", true);
        	//    		child.setBoolean(2, "B", true);
        	//    		CascadedTable grandChild = 
        	//    			new CascadedTable(child, new ColumnExpression("B"));
        	//    		grandChild.addColumn("C", int.class);
        	//    		grandChild.addColumn("D", int.class);
        	//    		grandChild.addColumn("E", int.class);
        	//    		grandChild.addColumn("F", int.class);
        	//    		grandChild.addColumn("G", int.class);
        	//    		System.out.println(grandChild.getBoolean(1, "B"));
        	col = parent.getColumnNumber(getTable().getColumnName(col));
            return parent.getColumnRow(getParentRow(row), col);
        }
        else
            return row;
    }
    
    /**
     * @see prefuse.data.util.RowManager#getTableRow(int, int)
     */
    public int getTableRow(int columnRow, int col) {
        int row;
        if ( col < ((CascadedTable)getTable()).getLocalColumnCount() ) {
            row = columnRow;
        } else {
            row = getChildRow(columnRow);
        }
        return isValidRow(row) ? row : -1;
    }
    
} // end of class CascadedRowManager
